" gray
highlight! CmpItemAbbrDeprecated guibg=NONE gui=strikethrough guifg=#808080
" blue
highlight! CmpItemAbbrMatch guibg=NONE guifg=#569CD6
highlight! link CmpItemAbbrMatchFuzzy CmpItemAbbrMatch
" light blue
highlight! CmpItemKindVariable guibg=NONE guifg=#9CDCFE
highlight! link CmpItemKindInterface CmpItemKindVariable
highlight! link CmpItemKindText CmpItemKindVariable
" pink
highlight! CmpItemKindFunction guibg=NONE guifg=#C586C0
highlight! link CmpItemKindMethod CmpItemKindFunction
" front
highlight! CmpItemKindKeyword guibg=NONE guifg=#D4D4D4
highlight! link CmpItemKindProperty CmpItemKindKeyword
highlight! link CmpItemKindUnit CmpItemKindKeyword

lua <<EOF
-- Set up nvim-cmp.
local cmp = require'cmp'

local has_words_before = function()
  local line, col = unpack(vim.api.nvim_win_get_cursor(0))
  return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end

local feedkey = function(key, mode)
	vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
end

local cmp_mapping = {
	['<C-b>'] = cmp.mapping.scroll_docs(-4),
	['<C-f>'] = cmp.mapping.scroll_docs(4),
	['<M-.>'] = cmp.mapping.complete(),
	['<C-e>'] = cmp.mapping.abort(),
	['<M-y>'] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
	["<Tab>"] = cmp.mapping(function(fallback)
		if cmp.visible() then
			cmp.select_next_item()
		elseif vim.fn["vsnip#available"](1) == 1 then
			feedkey("<Plug>(vsnip-expand-or-jump)", "")
		elseif has_words_before() then
			cmp.complete()
		else
			fallback()
		end
	end, { "i", "s" }),
	["<S-Tab>"] = cmp.mapping(function()
		if cmp.visible() then
			cmp.select_prev_item()
		elseif vim.fn["vsnip#jumpable"](-1) == 1 then
			feekey("<Plug>(vsnip-jump-prev)", "")
		end
	end, { "i", "s" }),
}
cmp_mapping["<C-j>"] = cmp_mapping["<Tab>"]
cmp_mapping["<M-j>"] = cmp_mapping["<Tab>"]
cmp_mapping["<C-k>"] = cmp_mapping["<S-Tab>"]
cmp_mapping["<M-k>"] = cmp_mapping["<S-Tab>"]

local kind_icons = {
	Text = "",
	Method = "",
	Function = "",
	Constructor = "",
	Field = "",
	Variable = "",
	Class = "ﴯ",
	Interface = "",
	Module = "",
	Property = "ﰠ",
	Unit = "",
	Value = "",
	Enum = "",
	Keyword = "",
	Snippet = "",
	Color = "",
	File = "",
	Reference = "",
	Folder = "",
	EnumMember = "",
	Constant = "",
	Struct = "",
	Event = "",
	Operator = "",
	TypeParameter = ""
}


local sources = {
	{ name = 'nvim_lsp' },
	{ name = 'vsnip' }, -- For vsnip users.
	{ name = 'buffer' },
	{ name = 'nvim_lsp_signature_help' },
}

vim.cmd('let g:local_machine=trim(system("uname -m"))')

-- tabnine 目前没有 arm 版本
if vim.g.local_machine ~= "aarch64" then
	local tabnine = require('cmp_tabnine.config')

	tabnine:setup({
		max_lines = 1000,
		max_num_results = 20,
		sort = true,
		run_on_every_keystroke = true,
		snippet_placeholder = '..',
		ignored_file_types = {
			-- default is not to ignore
			-- uncomment to ignore in lua:
			-- lua = true
		},
		show_prediction_strength = false
	})

	table.insert(sources, { name = 'cmp_tabnine' })
end

cmp.setup({
	snippet = {
		-- REQUIRED - you must specify a snippet engine
		expand = function(args)
			vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users.
			-- require('luasnip').lsp_expand(args.body) -- For `luasnip` users.
			-- require('snippy').expand_snippet(args.body) -- For `snippy` users.
			-- vim.fn["UltiSnips#Anon"](args.body) -- For `ultisnips` users.
		end,
	},
	window = {
		-- completion = cmp.config.window.bordered(),
		-- documentation = cmp.config.window.bordered(),
	},
	formatting = {
		format = function(entry, vim_item)
			-- This concatonates the icons with the name of the item kind
			vim_item.kind = string.format('%s %s', kind_icons[vim_item.kind], vim_item.kind) -- icon and kind
			-- vim_item.kind = kind_icons[vim_item.kind] -- icon only
			vim_item.menu = ({
				buffer = "[Buffer]",
				nvim_lsp = "[LSP]",
				luasnip = "[LuaSnip]",
				nvim_lua = "[Lua]",
				latex_symbols = "[LaTeX]",
				cmp_tabnine = "[TN]",
			})[entry.source.name]
			return vim_item
		end,
	},
	mapping = cmp.mapping.preset.insert(cmp_mapping),
	sources = sources,
})

  -- Set configuration for specific filetype.
  cmp.setup.filetype('gitcommit', {
    sources = cmp.config.sources({
      { name = 'cmp_git' }, -- You can specify the `cmp_git` source if you were installed it.
    }, {
      { name = 'buffer' },
    })
  })

  -- Use buffer source for `/` and `?` (if you enabled `native_menu`, this won't work anymore).
  -- cmp.setup.cmdline({ '/', '?' }, {
  --   mapping = cmp.mapping.preset.cmdline(),
  --   sources = {
  --     { name = 'buffer' }
  --   }
  -- })

  -- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
  -- cmp.setup.cmdline(':', {
  --   mapping = cmp.mapping.preset.cmdline(),
  --   sources = cmp.config.sources({
  --     { name = 'path' }
  --   }, {
  --     { name = 'cmdline' }
  --   })
  -- })

-- Set up lspconfig.
local nvim_lsp = require('lspconfig')

local on_attach = function(_, bufnr)
	-- require("lsp-format").on_attach(client)
	-- require("nvim-navic").attach(client, bufnr)

	vim.api.nvim_buf_set_option(bufnr, "omnifunc", "v:lua.vim.lsp.omnifunc")

	local opts = { noremap = true, silent = true }
	local map = vim.api.nvim_buf_set_keymap
	local keymap = vim.keymap.set
	-- use lspsaga.goto_definition instead.
	--map(bufnr, "n", "gD", "<cmd>lua vim.lsp.buf.declaration()<CR>", opts)
	map(bufnr, "n", "gD", "<cmd>Lspsaga peek_definition<CR>", opts)
	--map(bufnr, "n", "gd", "<cmd>lua vim.lsp.buf.definition()<CR>", opts)
	map(bufnr, "n", "gd", "<cmd>Lspsaga goto_definition<CR>", opts)
	--map(bufnr, "n", "K", "<cmd>lua vim.lsp.buf.hover()<CR>", opts)
	map(bufnr, "n", "K", "<cmd>Lspsaga hover_doc<CR>", opts)
	map(bufnr, "n","<leader>o", "<cmd>Lspsaga outline<CR>", opts)
	map(bufnr, "n", "gi", "<cmd>lua vim.lsp.buf.implementation()<CR>", opts)
	map(bufnr, 'n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
	map(bufnr, "n", "<leader>wa", "<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>", opts)
	map(bufnr, "n", "<leader>wr", "<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>", opts)
	map(bufnr, "n", "<leader>wl", "<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>", opts)
	map(bufnr, "n", "<leader>D", "<cmd>lua vim.lsp.buf.type_definition()<CR>", opts)
	map(bufnr, "n", "<leader>rn", "<cmd>lua vim.lsp.buf.rename()<CR>", opts)
	-- map(bufnr, "n", "<leader>rn", "<cmd>Lspsaga rename<CR>", opts)
	map(bufnr, "n", "gh", "<cmd>Lspsaga lsp_finder<CR>", opts)
	map(bufnr, 'n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
	--map(bufnr, "n", "<leader>ca", "<cmd>lua vim.lsp.buf.code_action()<CR>", opts)
	keymap({"n","v"}, "<leader>ca", "<cmd>Lspsaga code_action<CR>", { buffer = bufnr})
	map(bufnr, "n", "<leader>de", "<cmd>lua vim.diagnostic.open_float()<CR>", opts)
	map(bufnr, "n", "[d", "<cmd>lua vim.diagnostic.goto_prev()<CR>", opts)
	map(bufnr, "n", "]d", "<cmd>lua vim.diagnostic.goto_next()<CR>", opts)
	map(bufnr, "n", "<leader>dq", "<cmd>lua vim.diagnostic.setloclist()<CR>", opts)
	vim.cmd([[ command! Format execute 'lua vim.lsp.buf.formatting()' ]])
	-- goto preview keymappings
	map(bufnr, "n", "gp", "<cmd>lua require('goto-preview').goto_preview_definition()<CR>", opts)
	map(bufnr, "n", "gpi", "<cmd>lua require('goto-preview').goto_preview_implementation()<CR>", opts)
	map(bufnr, "n", "gpt", "<cmd>lua require('goto-preview').goto_preview_type_definition()<CR>", opts)
	map(bufnr, "n", "gq", "<cmd>lua require('goto-preview').close_all_win()<CR>", opts)
	map(bufnr, "n", "gF", "<cmd>lua require('goto-preview').goto_preview_references()<CR>", opts)
	-- format
	map(bufnr, "n", "<leader>lf", "<cmd>lua vim.lsp.buf.format()<CR>", opts)
end

local capabilities = require('cmp_nvim_lsp').default_capabilities()

local lsp_list = {
	bashls = "bash-language-server",
	bufls = "bufls",
	clangd = "clangd",
	cssls = "vscode-css-language-server",
	html = "vscode-html-language-server",
	intelephense = "intelephense",
	lua_ls = "lua-language-server",
	phpactor = "phpactor",
	pyright = "pyright",
	rust_analyzer = "rust-analyzer",
	tsserver = "typescript-language-server",
	vimls = "vim-language-server",
	yamlls = "yaml-language-server",
}

for lsp, cmd in pairs(lsp_list) do
	if vim.fn.executable(cmd) == 1 then
		nvim_lsp[lsp].setup {
			on_attach = on_attach,
			capabilities = capabilities,
		}
	end
end

nvim_lsp['gopls'].setup {
	cmd = {'gopls'},
	on_attach = on_attach,
	capabilities = capabilities,
	settings = {
		gopls = {
			gofumpt = true,
			completeUnimported = true,
			experimentalPostfixCompletions = true,
			analyses = {
				unusedparams = true,
				shadow = false,
			},
			staticcheck = true,
		},
	},
	init_options = {
		usePlaceholders = false,
	},
}

require("lspsaga").setup()

EOF
